/**
 * Copyright Marvell Inc
 */

package com.hisense.settings.util;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;

import java.util.List;

import com.android.settings.R;

/**
 * Utility Class to manager OSD widgets such as Activities
 * @author Marvell
 * @date 04 Dec 2012
 */
public class WidgetManager {
    // TAG used for LOG
    private static final String TAG = "WidgetManager";

    public static final String TV_PLAYER_ACTIVITY_NAME = "com.google.tv.player.PlayerActivity";

    /**
     * Set the preference's title to the matching activity's label.
     */
    private static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1;

    /**
     * Private constructor to prevent direct instantiation
     */
    private WidgetManager() {

    }

    public static void showFactoryMenu(final Context context) {
        createSingleTopActivity(TvIntents.ACTION_SHOW_FACTORY_MENU, null, context);
    }

    /*****************************************************************/
    /******* Generic Management ************/
    /*****************************************************************/

    public static void launchActivity(final Context context, final String packageName,
            final String className) {
        Intent intent = new Intent();
        ComponentName cn = new ComponentName(packageName, className);
        intent.setComponent(cn);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    /**
     * To exit form Main Menu
     * @param context
     *            application context
     */
    public static void exitFromApp(final Context context) {
        Log.d(TAG,
                "exitFromApp() called from class:"
                        + new Throwable().getStackTrace()[1].getClassName()
                        + " from method :" + new Throwable().getStackTrace()[1].getMethodName()
                        + " at line number " + new Throwable().getStackTrace()[1].getLineNumber());
        final Intent closeAppIntent = new Intent(TvIntents.INTENT_ACTION_CLOSE_APP);
        context.sendBroadcast(closeAppIntent);
    }

    /**
     * This is used by all activity to launch another activity.
     * @param activity
     *            activity to launch
     * @param context
     *            application context
     */
    public static void createSingleTopActivity(final Class<?> activity, final Context context) {
        createSingleTopActivity(activity, null, context);
    }

    /**
     * This is used by all activity to launch another activity.
     * @param activity
     *            activity to launch
     * @param bundle
     *            Extra data to be passed
     * @param context
     *            application context
     */
    public static void createSingleTopActivity(final Class<?> activity, final Bundle bundle,
            final Context context) {
        final Intent intent = new Intent(context, activity);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        context.startActivity(intent);
    }

    public static void createSingleTopActivity(final String action, final Bundle bundle,
            final Context context) {
        if (TextUtils.isEmpty(action) || context == null)
            return;

        Intent intent = new Intent(action);
        if (bundle != null)
            intent.putExtras(bundle);

        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    /**
     * To display progress dialog on cancellation of AlterDialog
     * @param context
     *            Activity instance
     * @return ProgressDialog instance
     */
    public static ProgressDialog showProgress(final Context context) {
        ProgressDialog progressDialog = ProgressDialog.show(context, "", "", true, false);
        progressDialog.setCancelable(false);
        progressDialog.show();
        progressDialog.setContentView(R.layout.progress_dialog_view);
        ((TextView) progressDialog.findViewById(R.id.progress_dialog_view_tv))
                .setText(R.string.progress_wait);
        return progressDialog;
    }

    /**
     * This method returns the activity component at the top of the history
     * stack of the task. This is what the user is currently doing.
     * @param context
     *            application context
     * @return activity name
     */
    public static String getTopActivityAtStack(final Context context) {

        String className = "";
        try {
            ActivityManager am = (ActivityManager) context
                    .getSystemService(Activity.ACTIVITY_SERVICE);

            /*
             * getRunningTasks(maxNum)->Return a list of the tasks that are
             * currently running, with the most recent being first and older
             * ones after in order.Here maxNum specifies the maximum number of
             * entries to return in the list. The actual number returned may be
             * smaller, depending on how many tasks the user has started. As we
             * passed 1 to getRunningTasks() it will return only 1 task which is
             * most recent task i.e. currently running task.
             */
            List<RunningTaskInfo> list = am.getRunningTasks(1);
            if (list != null && list.size() > 0) {
                className = list.get(0).topActivity.getClassName();
            } else {
                Log.e(TAG, "task list is empty");
            }
        } catch (Exception e) {

            Log.e(TAG, " Exception occured " + e);
        }
        Log.d(TAG, "getTopActivityAtStack()=" + className);
        return className;
    }

    public static boolean isLiveTvLaunched(Context mContext) {
        return checkActivityRunning(mContext, TV_PLAYER_ACTIVITY_NAME);
    }

    public static boolean isTopActivity(Context mContext, String activityName) {
        ActivityManager mActivityManager = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);

        List<RunningTaskInfo> list = mActivityManager.getRunningTasks(1);
        if (list != null && list.size() > 0) {
            String className = list.get(0).topActivity.getClassName();
            Log.d(TAG, "TopActivity className:" + className + ", activityName:" + activityName);
            if (className.equalsIgnoreCase(activityName)) {
                return true;
            }
        } else {
            Log.e(TAG, "task list is empty");
        }
        return false;
    }

    public static boolean checkActivityRunning(Context mContext, String activityName) {
        ActivityManager mActivityManager = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> taskList = mActivityManager.getRunningTasks(5);
        for (RunningTaskInfo info : taskList) {
            String className = info.topActivity.getClassName();
            Log.d(TAG, "checkActivityRunning className:" + className + ", activityName:"
                    + activityName);
            if (className.equalsIgnoreCase(activityName))
                return true;
        }
        return false;
    }

    public static boolean checkServiceRunning(Context mContext, String serviceName) {
        ActivityManager mActivityManager = (ActivityManager) mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningServiceInfo> serviceList = mActivityManager.getRunningServices(30);
        for (int i = 0; i < serviceList.size(); i++) {
            if (serviceName.equals(serviceList.get(i).service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Finds a matching activity for a preference's intent. If a matching
     * activity is not found, it will remove the preference.
     * @param context
     *            The context.
     * @param parentPreferenceGroup
     *            The preference group that contains the preference whose intent
     *            is being resolved.
     * @param preferenceKey
     *            The key of the preference whose intent is being resolved.
     * @param flags
     *            0 or one or more of
     *            {@link #UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY}
     *            .
     * @return Whether an activity was found. If false, the preference was
     *         removed.
     */
    public static boolean updatePreferenceToSpecificActivityOrRemove(Context context,
            PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags) {

        Preference preference = parentPreferenceGroup.findPreference(preferenceKey);
        if (preference == null) {
            return false;
        }

        Intent intent = preference.getIntent();
        if (intent != null) {
            // Find the activity that is in the system image
            PackageManager pm = context.getPackageManager();
            List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                ResolveInfo resolveInfo = list.get(i);
                if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
                != 0) {

                    // Replace the intent with this specific activity
                    preference.setIntent(new Intent().setClassName(
                            resolveInfo.activityInfo.packageName,
                            resolveInfo.activityInfo.name));

                    if ((flags & UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY) != 0) {
                        // Set the preference title to the activity's label
                        preference.setTitle(resolveInfo.loadLabel(pm));
                    }

                    return true;
                }
            }
        }

        // Did not find a matching activity, so remove the preference
        parentPreferenceGroup.removePreference(preference);

        return true;
    }
}
